package com.cm.etax.tianjin;

import com.cm.etax.BaseEtax;
import com.cm.etax.BaseFunction;
import com.cm.etax.EtaxConfig;
import com.cm.etax.FunctionResult;
import com.cm.etax.exceptions.EtaxException;
import com.cm.etax.tianjin.bean.SysApiResponse;
import com.cm.kits.RandomKits;
import com.cm.rpa.beans.Point;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.openqa.selenium.By;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebElement;

/**
 * 登录方法
 *
 * @author LWang 2023.01.29
 * @since 1.0.0
 */
@Slf4j
public class LoginFunction extends BaseFunction {

    public LoginFunction(BaseEtax etax) {
        super(etax);
    }


    /**
     * 天津市电子税务局登录
     *
     * @param taxpayerId     税号
     * @param personId       办税人 ID
     * @param personPassword 办税人密码
     */
    protected FunctionResult<Object> login(String taxpayerId, String personId, String personPassword) {
        config().setLoginType(EtaxConfig.LOGIN_TYPE_ENTERPRISE);
        try {
            rpa().visit(config().getMainUrl());
            tryLogout();
            rpa().visit(config().getDomain());
            tryCloseNotices();
            toLoginPage();
            tryLogin(taxpayerId, personId, personPassword);
            rpa().sleep(SLEEP_TIME);
            choiceRole();
            rpa().sleep(SLEEP_TIME);
            acceptJoin();
            rpa().sleep(SLEEP_TIME);
            ignoreSetPassword();
            rpa().sleep(SLEEP_TIME);
            if (!StringUtils.contains(rpa().url(), config().getHomeUri())) {
                throw new EtaxException("出现未预料的登录流程！");
            }
            // 尝试关闭通知
            return new FunctionResult<>(true, "登录成功。", null);
        } catch (Exception e) {
            return handleException(e, "登录失败，");
        }
    }

    /**
     * 忽略修改密码处理
     */
    protected void ignoreSetPassword() {
        if (StringUtils.contains(rpa().url(), config().getHomeUri())) {
            return;
        }
        try {
            rpa().waitElement(By.cssSelector("input.el-input__inner[placeholder=\"请设置密码\"]"), WAIT_TIME);
            rpa().refresh();
        } catch (NoSuchElementException ignore) {
        }
    }

    /**
     * 角色加入确认
     */
    protected void acceptJoin() {
        if (StringUtils.contains(rpa().url(), config().getHomeUri())) {
            return;
        }
        try {
            var dialogs = rpa().findElements(By.cssSelector(".el-message-box__wrapper .el-message-box"), WAIT_TIME);
            dialogs.forEach(dialog -> {
                if (rpa().inElementText(rpa().findElement(dialog, By.cssSelector(".el-message-box__container")), "")) {
                    rpa().click(rpa().findElementWithInnerText("确定", dialog, By.cssSelector(".el-message-box__btns button.el-button")));
                }
            });
        } catch (NoSuchElementException ignore) {
        }
    }

    /**
     * 选择角色
     */
    protected void choiceRole() {
        if (StringUtils.contains(rpa().url(), config().getHomeUri())) {
            return;
        }
        // 12. 如果没有进入电子税务局首页，判断是否有角色选择处理
        try {
            rpa().newHar();
            var choice = false;
            for (var role : etax().getRoles()) {
                try {
                    rpa().click(rpa().findElementWithInnerText(role, By.cssSelector(".el-radio .el-radio__label"), WAIT_TIME));
                    choice = true;
                    break;
                } catch (NoSuchElementException ignore) {
                }
            }
            if (!choice) {
                throw new EtaxException("无法识别的角色！");
            }
            rpa().click(By.cssSelector("div.el-dialog[aria-label=\"身份类型选择\"] button.el-button.el-button--primary"), WAIT_TIME);
            var response = rpa().jsonListen("auth/user/agreementListQuery", SysApiResponse.class);
            if (!response.success()) {
                throw new EtaxException(response.msg());
            }
        } catch (NoSuchElementException ignore) {
        }
    }

    /**
     * 尝试登录
     *
     * @param taxpayerId     税号
     * @param personId       办税人账号
     * @param personPassword 办税人密码
     */
    protected void tryLogin(String taxpayerId, String personId, String personPassword) {
        // 7. 切换到 企业业务 - 快捷登录 模式
        rpa().click(rpa().findElementWithInnerText("企业业务", By.cssSelector("div.justifyCenterEnd > span"), WAIT_TIME));
        rpa().click(rpa().findElementWithInnerText("快捷登录", By.cssSelector("div.card > div"), WAIT_TIME));
        // 8. 输入账号，密码
        rpa().sendKey(By.cssSelector("input[placeholder=\"统一社会信用代码/纳税人识别号\"]"), taxpayerId, true, WAIT_TIME);
        rpa().sendKey(By.cssSelector("input[placeholder=\"居民身份证号码/手机号码/用户名\"]"), personId, true, WAIT_TIME);
        rpa().sendKey(By.cssSelector("input[placeholder=\"个人用户密码(初始密码为证件号码后六位)\"]"), personPassword, true, WAIT_TIME);
        // 9. 滑动验证
        var dragHandler = rpa().findElement(By.cssSelector("div.drag > div.handler"), WAIT_TIME);
        rpa().moveTo(dragHandler);
        var drag = rpa().findElement(By.cssSelector("div.drag"));
        var handlerRect = rpa().sumElementRectangle(drag);
        rpa().dragTo(
                new Point(
                        RandomKits.nextDouble(handlerRect.rightTop().x(), handlerRect.rightTop().x() + MOUSE_OFFSET),
                        RandomKits.nextDouble(handlerRect.rightTop().y() - MOUSE_OFFSET, handlerRect.rightBottom().y()) + MOUSE_OFFSET
                )
        );
        // 10. 登录处理（监听登录 Ajax 结果）
        rpa().newHar();
        rpa().click(By.cssSelector("button.el-button.loginCls"), WAIT_TIME);
        var response = rpa().jsonListen("auth/enterprise/quick/accountLogin", SysApiResponse.class);
        if (!response.success()) {
            throw new EtaxException(response.msg());
        }
    }

    /**
     * 访问登录页面
     */
    protected void toLoginPage() {
        try {
            var loginButton = rpa().findElementWithInnerText("新版登录", By.cssSelector(".login-font"), WAIT_TIME);
            rpa().click(loginButton);
        } catch (NoSuchElementException e) {
            // 6. 找不到登录按钮，通过电子税务局内部脚本获取登录地址
            var loginUrl = rpa().executeJavaScript("return WSSW.kxLoingUrl", String.class);
            if (StringUtils.isBlank(loginUrl)) {
                throw new EtaxException("无法进入登录页面。");
            }
            rpa().visit(loginUrl);
        }
    }

    /**
     * 尝试关闭所有通知
     */
    protected void tryCloseNotices() {
        // 4. 尝试关闭所有通知框
        try {
            rpa().findElements(By.cssSelector("div.noticeContainer div.notice span.known"), WAIT_TIME).forEach(WebElement::click);
        } catch (NoSuchElementException ignored) {
            // 尝试性操作异常不需要处理
        }
    }

    /**
     * 尝试退出操作
     */
    protected void tryLogout() {
        // 2. 尝试进行退出操作
        try {
            rpa().waitElement(By.cssSelector("div.user span.userName span.userNameInfo"), WAIT_TIME);
            // 通过脚本进行退出操作
            rpa().newHar();
            rpa().executeJavaScript("""
                    (function() {
                        try {
                            WSSW.index.outWSSW();
                        } catch(e) {
                        }
                    })();
                    """, Object.class);
            rpa().listen("apps/view/login.html");
        } catch (Exception ignored) {
            // 尝试性操作异常不需要处理
        }
    }
}
